use regex::Regex;
use reqwest::blocking::get;
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;
use std::str::Lines;

fn main() {
    let path0 = Path::new("src/s2t_dict.rs");
    let path1 = Path::new("src/t2s_dict.rs");
    
    println!("cargo:rerun-if-changed={}", path0.display());
    println!("cargo:rerun-if-changed={}", path1.display());
    println!("cargo:rerun-if-changed=build.rs");

    let mediawiki_url = get("https://phabricator.wikimedia.org/source/mediawiki/browse/master/includes/languages/data/ZhConversion.php?view=raw").expect("MediaWki cannot be accessed! ");
    let zhc_url = mediawiki_url.url().as_str();

    let zhc = get(zhc_url).expect("MediaWiki cannot be accessed! ").text().unwrap();
    let (zhc, _) = zhc.split_once("	];\n\n	public const ZH_TO_TW = [").unwrap();
    let (_, zhc) = zhc.split_once("	public const ZH_TO_HANT = [").unwrap();
    let (mediawiki_hant, mediawiki_hans) = zhc.split_once("	];\n\n	public const ZH_TO_HANS = [").unwrap();

    let s2t_dict_list = vec![
        (DictType::LocalDict, include_str!("./STCustomDictionary.txt"), Regex::new(r"(\S+) (\S+)").unwrap()),
        (DictType::LocalDict, mediawiki_hant, Regex::new(r"'(\S+)' => '(\S+)',").unwrap()),
        (DictType::OnlineDict, "https://raw.githubusercontent.com/BYVoid/OpenCC/refs/heads/master/data/dictionary/STPhrases.txt", Regex::new(r"(\S+)\t(\S+)").unwrap()),
        (DictType::OnlineDict, "https://raw.githubusercontent.com/BYVoid/OpenCC/refs/heads/master/data/dictionary/STCharacters.txt", Regex::new(r"(\S+)\t(\S+)").unwrap()),
    ];
    
    let t2s_dict_list = vec![
        (DictType::LocalDict, include_str!("./TSCustomDictionary.txt"), Regex::new(r"(\S+) (\S+)").unwrap()),
        (DictType::LocalDict, mediawiki_hans, Regex::new(r"'(\S+)' => '(\S+)',").unwrap()),
        (DictType::OnlineDict, "https://raw.githubusercontent.com/BYVoid/OpenCC/refs/heads/master/data/dictionary/TSPhrases.txt", Regex::new(r"(\S+)\t(\S+)").unwrap()),
        (DictType::OnlineDict, "https://raw.githubusercontent.com/BYVoid/OpenCC/refs/heads/master/data/dictionary/TSCharacters.txt", Regex::new(r"(\S+)\t(\S+)").unwrap()),
    ];

    let mut file0 = BufWriter::new(File::create(&path0).unwrap());
    write!(&mut file0, "&[").unwrap();
    for (key, value) in get_dict_data(s2t_dict_list) {
        write!(&mut file0, "(\"{}\",\"{}\"),", key, value).unwrap();
    }
    writeln!(&mut file0, "]").unwrap();
    
    let mut file1 = BufWriter::new(File::create(&path1).unwrap());
    write!(&mut file1, "&[").unwrap();
    for (key, value) in get_dict_data(t2s_dict_list) {
        write!(&mut file1, "(\"{}\",\"{}\"),", key, value).unwrap();
    }
    writeln!(&mut file1, "]").unwrap();
}

enum DictType {
    LocalDict,
    OnlineDict,
}

#[inline(always)]
fn get_dict_data(dict_list: Vec<(DictType, &str, Regex)>) -> HashMap<String, String> {
    let mut dict = HashMap::new();
    for (dict_type, data, re) in dict_list {
        match dict_type {
            DictType::LocalDict => data_analysis(&mut dict, data.lines(), &re), 
            DictType::OnlineDict => {

                let r = get(data);
                if let Err(e) = r {
                    println!("Error: {}", e);
                }

                let data = get(data).expect("GitHub cannot be accessed! ").text().unwrap();
                data_analysis(&mut dict, data.lines(), &re)
            }
        }
    }
    dict
}

#[inline(always)]
fn data_analysis(map: &mut HashMap<String, String>, lines: Lines<'_>, re: &Regex) {
    for line in lines {
        let (_, [key, value]) = match re.captures(line) {
            Some(cap) => cap.extract(),
            None => continue,
        };
        if !map.contains_key(key) {
            map.insert(key.to_string(), value.to_string());
        }
    }
}